package com.unknow.first.geetest.util;

import static com.unknow.first.geetest.GeetestErrorEnum.GEETEST_API_RESPONSE_ERROR;

import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.unknow.first.geetest.config.GeetestConfig;
import com.unknow.first.geetest.vo.GeetestQueryParamVO;
import com.unknow.first.geetest.vo.GeetestValidateResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

@Slf4j
public final class GeetestCheckUtil {

    public GeetestValidateResultVO check(GeetestConfig geetestConfig, GeetestQueryParamVO queryParamVO) {
        String signToken = new HMac(HmacAlgorithm.HmacSHA256, geetestConfig.getCaptchaKey().getBytes()).digestHex(
            queryParamVO.getLotNumber());

        MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
        queryParams.add("lot_number", queryParamVO.getLotNumber());
        queryParams.add("captcha_output", queryParamVO.getCaptchaOutput());
        queryParams.add("pass_token", queryParamVO.getPassToken());
        queryParams.add("gen_time", queryParamVO.getGenTime());
        queryParams.add("sign_token", signToken);
        // captcha_id 参数建议放在 url 后面, 方便请求异常时可以在日志中根据id快速定位到异常请求
        // geetest recommends to put captcha_id parameter after url, so that when a request exception occurs, it can be quickly located in the log according to the id
        String url = String.format(geetestConfig.getDomain() + "/validate" + "?captcha_id=%s", geetestConfig.getCaptchaId());
        RestTemplate client = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        HttpMethod method = HttpMethod.POST;
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        try {
            HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(queryParams, headers);
            ResponseEntity<String> response = client.exchange(url, method, requestEntity, String.class);
            String resBody = response.getBody();

            JSONObject resBodyJson = JSONUtil.parseObj(resBody);
            if ("success".equals(resBodyJson.getStr("result"))) {
                return GeetestValidateResultVO.builder().pass(true).msg("success").build();
            }
            return GeetestValidateResultVO.builder().pass(false).msg(resBodyJson.getStr("reason")).build();
        } catch (Exception e) {
            return GeetestValidateResultVO.builder().pass(false).msg(GEETEST_API_RESPONSE_ERROR.i18n).build();
        }
    }

    public final static GeetestCheckUtil handler = new GeetestCheckUtil();

    @Lazy
    private GeetestCheckUtil() {

    }
}
